﻿// Q版泡泡堂.cpp : 此文件包含 "main" 函数。程序执行将在此处开始并结束。
//

/*
 * Q版泡泡堂
 * 
 * 1. 游戏简介
 *    操作你的英雄在规定时间内利用各种手段赢得高分或杀死对方吧！
 *
 * 2. 游戏操作说明
 *    (1). 按 "p" 或 "P" 开始游戏
 *    (2). 按 "detele" 退出游戏
 *    (3). 在游戏开始界面按空格键进入游戏说明
 *    (4). 在游戏未开始时，按 "Esc" 键返回游戏开始界面
 *    (5). 在游戏开始时，按 "Esc" 键暂停，按 "p" 或 "P" 继续游戏
 *    (6). 使用 "w" "s" "a" "d" 或 "W" "S" "A" "D" 分别控制英雄 1 的 “上” “下” “左” “右” 移动，空格键放炸弹。
 *    (7). 使用 "↑" "↓" "←" "→" 分别控制英雄 2 的 “上” “下” “左” “右” 移动，回车键放炸弹。
 *
 * 3. 开发思路
 * 
 */


#include <graphics.h>
#include <cstdio>
#include <cstdlib> // system();
#include <conio.h>
#include <ctime> // time();
#include <cstring>
#include <ios>
#include <Windows.h>

 /*
 * 有关图片基本输入输出的头文件
 * 1. struct node;
 *    用于储存文件名的链表节点的数据结构
 * 2. node* getFiles(char* filePath);
 *    读取指定目录下所有文件及文件夹名
 * 3. void load_image_from_file_folder(char* file_path, IMAGE** img, int* num);
 *    加载指定目录下的所有图片，主要用于制作逐帧动画
 * 4. void draw_png(const int picture_x, const int picture_y, IMAGE* picture);
 *    绘制带透明色的 png 图片
 */
#include "basic_play.h"

/*
 * 有关地图的头文件
 * 1. int rand_sort(int num[], int n);
 *    在已知整数集中随机选取一个数
 * 2. void rand_map();
 *    随机地图函数
 */
#include "map.h"

/*
 * 有关炸弹的头文件
 * 1. void draw_bomb(bomb* bombs, const wchar_t* hero_bomb_names);
 *    绘制炸弹函数
 * 2. void draw_bomb_e(bomb* bombs, hero* heroes, const wchar_t* hero_bomb_e_names);
 *    绘制炸弹痕迹函数
 */
#include "bomb.h"

/*
 * 有关英雄的头文件
 * 1. void hero_move(hero* heroes);
 *    英雄移动数据更新函数
 * 2. void draw_hero_move(hero* heroes);
 *    英雄移动绘制函数
 */
#include "hero.h"

/*
 * 有关音乐的头文件
 * 1. void play_music_once(const wchar_t* musics, const wchar_t* music_names);
 *    音乐播放函数
 * 2. void rand_background_music();
 *    游戏主界面随机背景音乐函数
 */
#include "music.h"

IMAGE* img_time_end = new IMAGE; // 定义“时间到”图片
IMAGE* img_game_end = new IMAGE; // 定义“游戏结束”图片

time_t t_start; // 记录游戏开始时间
time_t t_now; // 记录游戏当前时间
bool first = true; // 判断是否是第一次初始化数据

int start = 0; // 游戏是否执行
int game_end = 0; // 定义游戏结束标志位
bool game_close = false; // 定义退出游戏标志位


// 游戏主流程函数
void startup(); // 数据初始化
void startup_again(); // 数据二次初始化
void show(); // 显示画面
void update_without_input(); // 与用户输入无关的更新
void update_with_input(); // 与用户输入有关的更新
void game_over(); // 游戏结束

// 游戏主函数
int main()
{
	startup(); // 数据初始化
	while (game_close == false) // 进入游戏界面
	{
		if (start == 0) // 进入游戏开始界面
		{
			draw_png(0, 0, img_begin); // 绘制开始界面
			FlushBatchDraw(); // 输出图片
		}
		
		if (GetAsyncKeyState(static_cast<int>(' ')) & 0x8000) // 当按下空格键时候播放操作说明界面
		{
			start = 1; // 设置游戏行为判断
		}
		
		if (GetAsyncKeyState(static_cast<int>('p')) & 0x8000 || GetAsyncKeyState(static_cast<int>('P')) & 0x8000) // 当按下 p 键或 P 键时直接开始游戏
		{
			start = 2; // 设置游戏行为判断
			rand_background_music(); // 随机播放主界面背景音乐
		}
		
		while (start==1) // 显示游戏说明界面
		{
			draw_png(0, 0, img_operate); // 绘制游戏说明界面
			FlushBatchDraw(); // 输出图片
			
			if (GetAsyncKeyState(static_cast<int>('p')) & 0x8000 || GetAsyncKeyState(static_cast<int>('P')) & 0x8000) // 当按下 p 键或 P 键输出游戏画面
			{
				start = 2; // 设置游戏行为判断
				rand_background_music(); // 随机播放主界面背景音乐
			}
			else if (GetAsyncKeyState(VK_ESCAPE) & 0x8000) // 按下 Esc 键返回开始界面
			{
				start = 0; // 设置游戏行为判断
				break; // 退出游戏说明界面
			}
			else if (GetAsyncKeyState(VK_DELETE) & 0x8000) // 当按下 Delete 键时直接退出游戏
			{
				game_close = true; // 退出游戏
				break; // 退出游戏说明界面
			}
		}
		
		while (start == 2) // 进入游戏主界面
		{
			show(); // 显示游戏主界面
			update_without_input(); // 与用户输入无关的更新
			if (GetAsyncKeyState(VK_ESCAPE) & 0x8000) // 当按下 Esc 键时游戏暂停
			{
				while (game_close == false)
				{
					if (GetAsyncKeyState(static_cast<int>('p')) & 0x8000 || GetAsyncKeyState(static_cast<int>('P')) & 0x8000) // 当按下 "p" 或 "P" 时游戏继续
					{
						break;
					}
					if (GetAsyncKeyState(VK_DELETE) & 0x8000) // 当按下 Delete 键时直接退出游戏
					{
						game_close = true; // 退出游戏
						break; // 退出游戏暂停
					}
				}
			}
			if (GetAsyncKeyState(VK_DELETE) & 0x8000) // 当按下 Delete 键时直接退出游戏
			{
				game_close = true; // 退出游戏
				break; // 退出游戏主界面
			}
			if (game_end > 0) // 若游戏结束
			{
				startup_again(); // 再初始化游戏数据
				break; // 跳出游戏主界面
			}
			update_with_input(); // 与用户输入有关的更新
		}
		
		while (game_end == 1) // 若英雄 1 获胜
		{
			if (GetAsyncKeyState(VK_ESCAPE) & 0x8000 || GetAsyncKeyState(static_cast<int>(' ')) & 0x8000) // 当按下 Esc 键或空格键返回开始界面
			{
				game_end = 0; // 重置游戏结局判断
				start = 0; // 进入游戏开始界面
				break; // 退出游戏结局界面
			}
			if (GetAsyncKeyState(static_cast<int>('p')) & 0x8000 || GetAsyncKeyState(static_cast<int>('P')) & 0x8000) // 当按下 "p" 或 "P" 时直接重新开始游戏
			{
				game_end = 0; // 重置游戏结局判断
				start = 2; // 进入游戏主界面
				break; // 退出游戏结局界面
			}
			if (GetAsyncKeyState(VK_DELETE) & 0x8000) // 当按下 Delete 键时直接退出游戏
			{
				game_close = true; // 退出游戏
				break; // 退出游戏结局界面
			}
			draw_png(0, 0, hero_1->img_gameover); // 绘制英雄 1 胜利图片
			FlushBatchDraw(); // 输出图片
		}
		while (game_end == 2) // 若英雄 2 获胜
		{
			if (GetAsyncKeyState(VK_ESCAPE) & 0x8000 || GetAsyncKeyState(static_cast<int>(' ')) & 0x8000) // 当按下 Esc 键或空格键返回开始界面
			{
				game_end = 0; // 重置游戏结局判断
				start = 0; // 进入游戏开始界面
				break; // 退出游戏结局界面
			}
			if (GetAsyncKeyState(static_cast<int>('p')) & 0x8000 || GetAsyncKeyState(static_cast<int>('P')) & 0x8000) // 当按下 "p" 或 "P" 时直接重新开始游戏
			{
				game_end = 0; // 重置游戏结局判断
				start = 2; // 进入游戏主界面
				break; // 退出游戏结局界面
			}
			if (GetAsyncKeyState(VK_DELETE) & 0x8000) // 当按下 Delete 键时直接退出游戏
			{
				game_close = true; // 退出游戏
				break; // 退出游戏结局界面
			}
			draw_png(0, 0, hero_2->img_gameover); // 绘制英雄 2 胜利图片
			FlushBatchDraw(); // 输出图片
		}
		while (game_end == 3) // 若为平局
		{
			if (GetAsyncKeyState(VK_ESCAPE) & 0x8000 || GetAsyncKeyState(static_cast<int>(' ')) & 0x8000) // 当按下 Esc 键或空格键返回开始界面
			{
				game_end = 0; // 重置游戏结局判断
				start = 0; // 进入游戏开始界面
				break; // 退出游戏结局界面
			}
			if (GetAsyncKeyState(static_cast<int>('p')) & 0x8000 || GetAsyncKeyState(static_cast<int>('P')) & 0x8000) // 当按下 "p" 或 "P" 时直接重新开始游戏
			{
				game_end = 0; // 重置游戏结局判断
				start = 2; // 进入游戏主界面
				break; // 退出游戏结局界面
			}
			if (GetAsyncKeyState(VK_DELETE) & 0x8000) // 当按下 Delete 键时直接退出游戏
			{
				game_close = true; // 退出游戏
				break; // 退出游戏结局界面
			}
			draw_png(0, 0, img_samewiner); // 绘制平局图片
			FlushBatchDraw(); // 输出图片
		}

		if (GetAsyncKeyState(VK_DELETE) & 0x8000) // 当按下 Delete 键时直接退出游戏
		{
			break; // 退出游戏
		}
	}
	game_over(); // 游戏结束后续处理
	return 0;
}


// 数据初始化
void startup()
{
	srand(static_cast<unsigned int>(time(nullptr))); // 取游戏启动系统时间为随机数种子

	// 随机播放背景音乐
	mciSendString(_T("close background_music"), nullptr, 0, nullptr); // 把前面一次的音乐关闭
	mciSendString(_T(R"(open ".\musics\Bombit_-_mainscreen.mp3" alias background_music)"), nullptr, 0, nullptr); // 打开背景音乐
	mciSendString(_T("play background_music repeat"), nullptr, 0, nullptr); // 循环播放
	
	AddFontResource(LR"(.\font\font.ttf)");// 添加游戏字体
	loadimage(hero_1->img_gameover, _T(R"(.\images\ui\play_ui\1Pwiner.png)")); // 载入英雄 1 获胜的结束界面
	loadimage(hero_2->img_gameover, _T(R"(.\images\ui\play_ui\2Pwiner.png)")); // 载入英雄 2 获胜的结束界面
	loadimage(img_samewiner, _T(R"(.\images\ui\play_ui\samewiner.png)")); // 载入英雄 2 获胜的结束界面
	loadimage(img_operate, _T(R"(.\images\ui\play_ui\operate.png)")); // 载入操作界面的说明
	loadimage(img_begin, _T(R"(.\images\ui\play_ui\begin.png)")); // 载入开始界面图
	loadimage(img_bk, _T(R"(.\images\ui\play_ui\background.png)")); // 载入背景图
	initgraph(img_bk->getwidth(), img_bk->getheight()); // 根据背景图大小改变游戏画面大小

	// 载入地图相关图片
	load_image_from_file_folder(const_cast<char*>(R"(.\images\maps\bg\*)"), &img_bg, &bg_num); // 载入地板样式图片
	load_image_from_file_folder(const_cast<char*>(R"(.\images\maps\brick_all\brick\*)"), &img_brick, &brick_num); // 载入砖块样式图片
	load_image_from_file_folder(const_cast<char*>(R"(.\images\maps\brick_all\brick_center\*)"), &img_brick_center,&brick_center_num); // 载入中心砖块样式图片
	load_image_from_file_folder(const_cast<char*>(R"(.\images\maps\brick_all\brick_crack\*)"), &img_brick_crack, &brick_crack_num); // 载入可破坏砖块样式图片
	load_image_from_file_folder(const_cast<char*>(R"(.\images\maps\tools\*)"), &img_tools,&tools_num); // 载入可破坏砖块样式图片
	load_image_from_file_folder(const_cast<char*>(R"(.\images\maps\tools\*)"), &img_tools, &tools_num); // 载入道具图片

	// 载入英雄 1 相关数据
	loadimage(&hero_1->img_head, _T(R"(.\images\heroes\hero_1\head.png)")); // 载入英雄 1 头像
	loadimage(&hero_1->img_stand_up, _T(R"(.\images\heroes\hero_1\stand\1.png)")); // 载入英雄 1 向上站立图片
	loadimage(&hero_1->img_stand_down, _T(R"(.\images\heroes\hero_1\stand\2.png)")); // 载入英雄 1 向下站立图片
	loadimage(&hero_1->img_stand_left, _T(R"(.\images\heroes\hero_1\stand\3.png)")); // 载入英雄 1 向左站立图片
	loadimage(&hero_1->img_stand_right, _T(R"(.\images\heroes\hero_1\stand\4.png)")); // 载入英雄 1 向右站立图片
	load_image_from_file_folder(const_cast<char*>(R"(.\images\heroes\hero_1\up\*)"), &hero_1->img_walk_up,&hero_1->walk_up_num); // 载入英雄 1 向上行走图片
	load_image_from_file_folder(const_cast<char*>(R"(.\images\heroes\hero_1\down\*)"), &hero_1->img_walk_down, &hero_1->walk_down_num); // 载入英雄 1 向下行走图片
	load_image_from_file_folder(const_cast<char*>(R"(.\images\heroes\hero_1\left\*)"), &hero_1->img_walk_left, &hero_1->walk_left_num); // 载入英雄 1 向左行走图片
	load_image_from_file_folder(const_cast<char*>(R"(.\images\heroes\hero_1\right\*)"), &hero_1->img_walk_right, &hero_1->walk_right_num); // 载入英雄 1 向右行走图片

	// 载入英雄 2 相关数据
	loadimage(&hero_2->img_head, _T(R"(.\images\heroes\hero_2\head.png)")); // 载入英雄 2 头像
	loadimage(&hero_2->img_stand_up, _T(R"(.\images\heroes\hero_2\stand\1.png)")); // 载入英雄 2 向上站立图片
	loadimage(&hero_2->img_stand_down, _T(R"(.\images\heroes\hero_2\stand\2.png)")); // 载入英雄 2 向下站立图片
	loadimage(&hero_2->img_stand_left, _T(R"(.\images\heroes\hero_2\stand\3.png)")); // 载入英雄 2 向左站立图片
	loadimage(&hero_2->img_stand_right, _T(R"(.\images\heroes\hero_2\stand\4.png)")); // 载入英雄 2 向右站立图片
	load_image_from_file_folder(const_cast<char*>(R"(.\images\heroes\hero_2\up\*)"), &hero_2->img_walk_up,&hero_2->walk_up_num); // 载入英雄 2 向上行走图片
	load_image_from_file_folder(const_cast<char*>(R"(.\images\heroes\hero_2\down\*)"), &hero_2->img_walk_down,&hero_2->walk_down_num); // 载入英雄 2 向下行走图片
	load_image_from_file_folder(const_cast<char*>(R"(.\images\heroes\hero_2\left\*)"), &hero_2->img_walk_left,&hero_2->walk_left_num); // 载入英雄 2 向左行走图片
	load_image_from_file_folder(const_cast<char*>(R"(.\images\heroes\hero_2\right\*)"), &hero_2->img_walk_right,&hero_2->walk_right_num); // 载入英雄 2 向右行走图片

	loadimage(img_shade, _T(R"(.\images\heroes\shade.png)")); // 载入行走阴影
	loadimage(img_head_shade, _T(R"(.\images\heroes\head_shade.png)")); // 载入头像阴影
	loadimage(hero_1->img_character, _T(R"(.\images\heroes\hero_1\character.png)"));//载入角色1
	loadimage(hero_2->img_character, _T(R"(.\images\heroes\hero_2\character.png)"));//载入角色2
	load_image_from_file_folder(const_cast<char*>(R"(.\images\heroes\hero_exp\*)"), &img_hero_death, &img_hero_death_num); // 载入英雄死亡动画
	load_image_from_file_folder(const_cast<char*>(R"(.\images\heroes\hero_die_smoke\*)"), &img_hero_death_smoke,&img_hero_death_smoke_num); // 载入英雄死亡烟雾动画
	loadimage(img_hero_death_shade,_T(R"(.\images\heroes\death_shade.png)")); // 载入英雄死亡阴影图
	
	load_image_from_file_folder(const_cast<char*>(R"(.\images\maps\bomb\*)"), &img_bomb, &bomb_num); // 载入炸弹的动态数据
	load_image_from_file_folder(const_cast<char*>(R"(.\images\maps\bombex\bombex1\*)"), &hero_1->img_bomb_e, &hero_1->img_bomb_e_num); // 载入爆炸 1 相关数据
	load_image_from_file_folder(const_cast<char*>(R"(.\images\maps\bombex\bombex2\*)"), &hero_2->img_bomb_e, &hero_2->img_bomb_e_num); // 载入爆炸 2 相关数据

	loadimage(img_time_end, _T(R"(.\images\ui\play_ui\time_end.png)")); // 载入“时间到”图片
	loadimage(img_game_end, _T(R"(.\images\ui\play_ui\game_end.png)")); // 载入“游戏结束”图片
	
	// 随机英雄 1、2 的出生地
	int birth_carry[4] = { 1,2,3,4 }; // 定义随机出生地数组
	rand_sort(birth_carry, 4); // 打乱出生地数组
	// 对英雄 1
	if (birth_carry[0] == 1) // 1 出生地
	{
		hero_1->x = 89 + 30 * 3;
		hero_1->y = -19 + 30 * 3;
	}
	else if (birth_carry[0] == 2) // 2 出生地
	{
		hero_1->x = 89 + 30 * 11;
		hero_1->y = -19 + 30 * 3;
	}
	else if (birth_carry[0] == 3) // 3 出生地
	{
		hero_1->x = 89 + 30 * 3;
		hero_1->y = -19 + 30 * 9;
	}
	else if (birth_carry[0] == 4) // 4 出生地
	{
		hero_1->x = 89 + 30 * 11;
		hero_1->y = -19 + 30 * 9;
	}
	// 对英雄 2
	if (birth_carry[1] == 1) // 1 出生地
	{
		hero_2->x = 89 + 30 * 3;
		hero_2->y = -19 + 30 * 3;
	}
	else if (birth_carry[1] == 2) // 2 出生地
	{
		hero_2->x = 89 + 30 * 11;
		hero_2->y = -19 + 30 * 3;
	}
	else if (birth_carry[1] == 3) // 3 出生地
	{
		hero_2->x = 89 + 30 * 3;
		hero_2->y = -19 + 30 * 9;
	}
	else if (birth_carry[1] == 4) // 4 出生地
	{
		hero_2->x = 89 + 30 * 11;
		hero_2->y = -19 + 30 * 9;
	}

	// 设定已知砖块的标志位
	// 1 出生点
	(map_cell + 2 + 2 * 15)->fix_brick = true;
	(map_cell + 4 + 2 * 15)->fix_brick = true;
	(map_cell + 2 + 4 * 15)->fix_brick = true;
	(map_cell + 4 + 4 * 15)->fix_brick = true;
	// 2 出生点
	(map_cell + 10 + 2 * 15)->fix_brick = true;
	(map_cell + 12 + 2 * 15)->fix_brick = true;
	(map_cell + 10 + 4 * 15)->fix_brick = true;
	(map_cell + 12 + 4 * 15)->fix_brick = true;
	// 3 出生点
	(map_cell + 2 + 8 * 15)->fix_brick = true;
	(map_cell + 4 + 8 * 15)->fix_brick = true;
	(map_cell + 2 + 10 * 15)->fix_brick = true;
	(map_cell + 4 + 10 * 15)->fix_brick = true;
	// 4 出生点
	(map_cell + 10 + 8 * 15)->fix_brick = true;
	(map_cell + 12 + 8 * 15)->fix_brick = true;
	(map_cell + 10 + 10 * 15)->fix_brick = true;
	(map_cell + 12 + 10 * 15)->fix_brick = true;

	// 设定已知空地的标志位
	// 1 出生点
	(map_cell + 3 + 1 * 15)->fix_empty = true;
	(map_cell + 1 + 3 * 15)->fix_empty = true;
	(map_cell + 5 + 3 * 15)->fix_empty = true;
	(map_cell + 3 + 5 * 15)->fix_empty = true;
	// 2 出生点
	(map_cell + 11 + 1 * 15)->fix_empty = true;
	(map_cell + 9 + 3 * 15)->fix_empty = true;
	(map_cell + 13 + 3 * 15)->fix_empty = true;
	(map_cell + 11 + 5 * 15)->fix_empty = true;
	// 3 出生点
	(map_cell + 3 + 7 * 15)->fix_empty = true;
	(map_cell + 1 + 9 * 15)->fix_empty = true;
	(map_cell + 5 + 9 * 15)->fix_empty = true;
	(map_cell + 3 + 11 * 15)->fix_empty = true;
	// 4 出生点
	(map_cell + 11 + 7 * 15)->fix_empty = true;
	(map_cell + 9 + 9 * 15)->fix_empty = true;
	(map_cell + 13 + 9 * 15)->fix_empty = true;
	(map_cell + 11 + 11 * 15)->fix_empty = true;
	// 中心方块
	(map_cell + 6 + 5 * 15)->fix_empty = true;
	(map_cell + 7 + 5 * 15)->fix_empty = true;
	(map_cell + 6 + 6 * 15)->fix_empty = true;
	(map_cell + 7 + 6 * 15)->fix_empty = true;

	// 初始化地图坐标数据
	for (auto i = 0; i < 13; i++)
	{
		for (auto j = 0; j < 15; j++)
		{
			(map_cell + j + i * 15)->x = 93 + j * 30; // 定义地图块 x 坐标
			(map_cell + j + i * 15)->y = 5 + i * 30; // 定义地图块 y 坐标
		}
	}

	rand_map(); // 随机生成地图

	BeginBatchDraw(); // 全部绘制
}

/*
 * 数据再初始化函数
 * 用于在游戏界面重新开始游戏时的数据初始化
 */
void startup_again()
{
	// 播放游戏开始界面音乐
	mciSendString(_T("close background_music"), nullptr, 0, nullptr); // 把前面一次的音乐关闭
	mciSendString(_T(R"(open ".\musics\Bombit_-_mainscreen.mp3" alias background_music)"), nullptr, 0, nullptr); // 打开背景音乐
	mciSendString(_T("play background_music repeat"), nullptr, 0, nullptr); // 循环播放

	// 再初始化英雄数据
	// 再初始化英雄 1 数据
	hero_1->stand_direction = direction::down; // 站立方向为向下
	hero_1->move_direction = direction::stand; // 静止站立
	hero_1->times = 0; // 图片帧数计数器归零
	hero_1->pixel = 0; // 移动像素计数器归零
	hero_1->bomb_num = 1; // 炸弹数重置为 1
	hero_1->death = false; // 死亡判定重置为假
	hero_1->hero_death = 0; // 死亡动画播放计数器重置为 0
	hero_1->score = 0; // 英雄得分重置为零
	// 再初始化英雄 2 数据
	hero_2->stand_direction = direction::down; // 站立方向为向下
	hero_2->move_direction = direction::stand; // 静止站立
	hero_2->times = 0; // 图片帧数计数器归零
	hero_2->pixel = 0; // 移动像素计数器归零
	hero_2->bomb_num = 1; // 炸弹数重置为 1
	hero_2->death = false; // 死亡判定重置为假
	hero_2->hero_death = 0; // 死亡动画播放计数器重置为 0
	hero_2->score = 0; // 英雄得分重置为零

	// 再初始化炸弹的数据
	// 再初始化炸弹 1 的数据
	bomb_1->bomb_judge = 0;
	bomb_1->time_s = 0;
	bomb_1->bomb_destroy = 0;
	// 再初始化炸弹 2 的数据
	bomb_1->bomb_judge = 0;
	bomb_1->time_s = 0;
	bomb_1->bomb_destroy = 0;

	// 再次随机英雄 1、2 的出生地
	int birth_carry[4] = { 1,2,3,4 }; // 定义随机出生地数组
	rand_sort(birth_carry, 4); // 打乱出生地数组
	// 对英雄 1
	if (birth_carry[0] == 1) // 1 出生地
	{
		hero_1->x = 89 + 30 * 3;
		hero_1->y = -19 + 30 * 3;
	}
	else if (birth_carry[0] == 2) // 2 出生地
	{
		hero_1->x = 89 + 30 * 11;
		hero_1->y = -19 + 30 * 3;
	}
	else if (birth_carry[0] == 3) // 3 出生地
	{
		hero_1->x = 89 + 30 * 3;
		hero_1->y = -19 + 30 * 9;
	}
	else if (birth_carry[0] == 4) // 4 出生地
	{
		hero_1->x = 89 + 30 * 11;
		hero_1->y = -19 + 30 * 9;
	}
	// 对英雄 2
	if (birth_carry[1] == 1) // 1 出生地
	{
		hero_2->x = 89 + 30 * 3;
		hero_2->y = -19 + 30 * 3;
	}
	else if (birth_carry[1] == 2) // 2 出生地
	{
		hero_2->x = 89 + 30 * 11;
		hero_2->y = -19 + 30 * 3;
	}
	else if (birth_carry[1] == 3) // 3 出生地
	{
		hero_2->x = 89 + 30 * 3;
		hero_2->y = -19 + 30 * 9;
	}
	else if (birth_carry[1] == 4) // 4 出生地
	{
		hero_2->x = 89 + 30 * 11;
		hero_2->y = -19 + 30 * 9;
	}

	// 再初始化地图数据
	for (auto i = 0; i < 195; i++)
	{
		(map_cell + i)->brick = 0; // 再初始化砖块样式
		(map_cell + i)->brick_crack = 0; // 再初始化可破坏砖块样式
		(map_cell + i)->tools = 0; // 再初始化道具样式
		(map_cell + i)->if_bomb = false; // 全部非炸弹
		(map_cell + i)->if_death = false; // 全部非死地
	}
	rand_map(); // 再初始化地图

	first = true; // 记为再次初始化数据
}


// 显示画面
void show()
{
	draw_png(0, 0, img_bk); // 显示背景
	
	// 显示英雄头像
	draw_png(23, 20, &hero_1->img_head);
	draw_png(25, 20 + 68, &hero_2->img_head);
	draw_png(23, 19 + 68 * 2, img_head_shade);
	draw_png(23, 19 + 68 * 3, img_head_shade);

	// 显示英雄死亡阴影图
	if (hero_1->death == true) // 若英雄 1 死亡
	{
		draw_png(14, 19, img_hero_death_shade); // 英雄 1 你已死
	}
	if (hero_2->death == true) // 若英雄 2 死亡
	{
		draw_png(14, 86, img_hero_death_shade); // 英雄 2 你已死
	}
	draw_png(14, 153, img_hero_death_shade); // 英雄 3 早逝
	draw_png(14, 220, img_hero_death_shade); // 英雄 4 早逝
	
	// 绘制地图
	auto i = 0;
	for (; i < 13; i++) // 绘制第二层图层
	{
		for (auto j = 0; j < 15; j++)
		{
			draw_png((map_cell + j + i * 15)->x, (map_cell + j + i * 15)->y, img_bg + bg - 1); // 绘制地板
		}
	}

	// 放在这里可解决图层覆盖问题和循环遍历带来的性能问题
	draw_bomb_e(bomb_1, hero_1,_T("hero_1_bomb_e")); // 绘制炸弹痕迹 1
	draw_bomb_e(bomb_2, hero_2, _T("hero_2_bomb_e")); // 绘制炸弹痕迹 2
	
	i = 0;
	for (; i < 13; i++) // 绘制第三层图层
	{
		for (auto j = 14; j >= 0; j--) // 反向遍历，让墙的覆盖顺序正确
		{
			if (i == 6 && j == 4) // 中部绘制，让墙的覆盖顺序正确
			{
				draw_png(93 + 6 * 30 - 13, 5 + 5 * 30 - 30, img_brick_center + brick_center - 1); // 绘制中心大墙
			}
			if ((map_cell + j + i * 15)->brick > 0) // 若是砖块
			{
				draw_png((map_cell + j + i * 15)->x - 12, (map_cell + j + i * 15)->y - 37,img_brick + (map_cell + j + i * 15)->brick - 1); // 绘制砖块
			}
			if ((map_cell + j + i * 15)->brick_crack > 0) // 若是可破坏砖块
			{
				draw_png((map_cell + j + i * 15)->x - 12, (map_cell + j + i * 15)->y - 37,img_brick_crack + (map_cell + j + i * 15)->brick_crack - 1); // 绘制可破坏砖块
			}
			if ((map_cell + j + i * 15)->tools > 0) // 若是道具
			{
				draw_png((map_cell + j + i * 15)->x , (map_cell + j + i * 15)->y - 5, img_tools + (map_cell + j + i * 15)->tools - 1); // 绘制道具
			}
			draw_png(10, 15, hero_1->img_character); // 绘制 1P
			draw_png(10, 80, hero_2->img_character); // 绘制 2P
		}

		// 绘制炸弹 1
		if (static_cast<float>(i) >= (static_cast<float>(bomb_1->bomb_y) + 19) / 30 && static_cast<float>(i) < (static_cast<float>(bomb_1->bomb_y) + 19) / 30 + 1) // 该条件使人物图层覆盖正确
		{
			draw_bomb(bomb_1, _T("hero_1_bomb"));
		}
		// 绘制炸弹 2
		if (static_cast<float>(i) >= (static_cast<float>(bomb_2->bomb_y) + 19) / 30 && static_cast<float>(i) < (static_cast<float>(bomb_2->bomb_y) + 19) / 30 + 1) // 该条件使人物图层覆盖正确
		{
			draw_bomb(bomb_2, _T("hero_2_bomb"));
		}

		// 绘制英雄 1
		if (hero_1->death == false && static_cast<float>(i) >= (static_cast<float>(hero_1->y) + 19) / 30 && static_cast<float>(i) < (static_cast<float>(hero_1->y) + 19) / 30 + 1)
		{
			draw_hero_move(hero_1);
		}
		else if (hero_1->death == true && hero_1->hero_death / 4 < img_hero_death_num) // 若死亡
		{
			Sleep(2);
			draw_png(hero_1->x - 15, hero_1->y - 25, img_hero_death + hero_1->hero_death / 4); // 绘制英雄死亡动画
			hero_1->hero_death++; // 记录英雄死亡动画显示帧数
		}
		else if (hero_1->death == true && hero_1->hero_death / 4 - img_hero_death_num < img_hero_death_smoke_num) // 绘制死亡烟雾
		{
			Sleep(2);
			draw_png(hero_1->x + 5, hero_1->y - 5, img_hero_death_smoke + hero_1->hero_death / 4 - img_hero_death_num);
			hero_1->hero_death++; // 记录英雄死亡动画显示帧数
		}
		else if (hero_1->death == true)
		{
			Sleep(2);
			hero_1->hero_death++; // 用于维持游戏主界面一段时间
		}

		// 绘制英雄 2
		if (hero_2->death == false && static_cast<float>(i) >= (static_cast<float>(hero_2->y) + 19) / 30 && static_cast<float>(i) < (static_cast<float>(hero_2->y) + 19) / 30 + 1)
		{
			draw_hero_move(hero_2);
		}
		else if (hero_2->death == true && hero_2->hero_death / 4 < img_hero_death_num) // 若死亡
		{
			Sleep(2);
			draw_png(hero_2->x - 15, hero_2->y - 25, img_hero_death + hero_2->hero_death / 4); // 绘制英雄死亡动画
			hero_2->hero_death++; // 记录英雄死亡动画显示帧数
		}
		else if (hero_2->death == true && hero_2->hero_death / 4 - img_hero_death_num < img_hero_death_smoke_num) // 绘制死亡烟雾
		{
			Sleep(2);
			draw_png(hero_2->x + 5, hero_2->y - 5, img_hero_death_smoke + hero_2->hero_death / 4 - img_hero_death_num);
			hero_2->hero_death++; // 记录英雄死亡动画显示帧数
		}
		else if (hero_2->death == true)
		{
			Sleep(2);
			hero_2->hero_death++; // 用于维持游戏主界面一段时间
		}
	}

	// 文字绘制
	// 显示得分 1
	setbkmode(TRANSPARENT);
	LOGFONT f;
	gettextstyle(&f);
	f.lfHeight = 20; // 定义字号
	_tcscpy_s(f.lfFaceName, _T("宋体")); // 定义字体
	f.lfQuality = ANTIALIASED_QUALITY; // 高质量输出
	settextstyle(&f);
	TCHAR s[5];
	_stprintf_s(s, _T("%d"), hero_1->score);
	outtextxy(15, 58, s); // 输出分数
	// 显示得分 2
	setbkmode(TRANSPARENT);
	LOGFONT f2;
	gettextstyle(&f2);
	f2.lfHeight = 20; // 定义字号
	_tcscpy_s(f2.lfFaceName, _T("宋体")); // 定义字体
	f2.lfQuality = ANTIALIASED_QUALITY; // 高质量输出
	settextstyle(&f2);
	TCHAR s2[5];
	_stprintf_s(s2, _T("%d"), hero_2->score);
	outtextxy(15, 125, s2); // 输出分数
	// 显示“倒计时”
	setbkmode(TRANSPARENT);
	gettextstyle(&f);
	f.lfHeight = 12; // 定义字号
	_tcscpy_s(f.lfFaceName, _T("宋体")); // 定义字体
	f.lfQuality = ANTIALIASED_QUALITY; // 高质量输出
	settextstyle(&f);
	outtextxy(10, 320, _T("倒计时"));
	
	// 显示倒计时
	setbkmode(TRANSPARENT);
	gettextstyle(&f);
	f.lfHeight = 18; // 定义字号
	_tcscpy_s(f.lfFaceName, _T("宋体"));
	f.lfQuality = ANTIALIASED_QUALITY;
	settextstyle(&f);
	// 显示零
	outtextxy(14, 335, '0');
	// 显示分钟
	TCHAR  minute[5];
	_stprintf_s(minute, _T("%d"), static_cast<int>(t_now) / 60); // 取分钟
	outtextxy(29, 335, minute);
	// 显示秒钟十位
	TCHAR second_10[5];
	_stprintf_s(second_10, _T("%d"), static_cast<int>(t_now) % 60 / 10); // 取秒钟十位
	outtextxy(53, 335, second_10);
	// 显示秒钟个位
	TCHAR second_1[5];
	_stprintf_s(second_1, _T("%d"), static_cast<int>(t_now) % 60 % 10); // 取秒钟个位
	outtextxy(68, 335, second_1);

	FlushBatchDraw(); // 全部一起绘制

	if (first == true) // 若刚刚进行了数据初始化
	{
		t_start = time(nullptr); // 返回从 1970 年 1 月 1 日至今所经历的时间(秒)
		first = false; // 标志位设为假
	}
}

// 与用户输入有关的更新
void update_with_input()
{
	// 更新英雄数据
	hero_move(hero_1);
	hero_move(hero_2);
	
	// 英雄 1 不死且英雄 1 的上一个炸弹爆炸且按下空格爆炸的情况下产生炸弹 1
	if (hero_1->death == false && hero_1->bomb_num > 0 && GetAsyncKeyState(static_cast<int>(' ')) & 0x8000)
	{
		bomb_1->bomb_x = (hero_1->x - 89) / 30 * 30 + 89; // 把英雄 1 的当前坐标规范化生成炸弹坐标
		bomb_1->bomb_y = (hero_1->y + 19) / 30 * 30 - 19; // 把英雄 1 的当前坐标规范化生成炸弹坐标
		(map_cell + (hero_1->x - 89) / 30 + (hero_1->y + 19) / 30 * 15)->if_bomb = true; // 设置炸弹标志位
		bomb_1->bomb_judge= 1; // 初始化爆炸判断
		hero_1->bomb_num--; // 英雄 1 炸弹数目减一
	}
	// 英雄 2 不死且英雄 2 的上一个炸弹爆炸且按下空格爆炸的情况下产生炸弹 2
	if (hero_2->death == false && hero_2->bomb_num > 0 && GetAsyncKeyState(VK_RETURN) & 0x8000)
	{
		bomb_2->bomb_x = (hero_2->x - 89) / 30 * 30 + 89; // 把英雄 1 的当前坐标规范化生成炸弹坐标
		bomb_2->bomb_y = (hero_2->y + 19) / 30 * 30 - 19; // 把英雄 1 的当前坐标规范化生成炸弹坐标
		(map_cell + (hero_2->x - 89) / 30 + (hero_2->y + 19) / 30 * 15)->if_bomb = true; // 设置炸弹标志位
		bomb_2->bomb_judge = 1; // 初始化爆炸判断
		hero_2->bomb_num--; // 英雄 2 炸弹数目减一
	}
	
	// 判断英雄 1 上一轮移动是否完成
	if (hero_1->death == false && hero_1->move_direction == direction::stand) // 若完成
	{
		if (GetAsyncKeyState(static_cast<int>('w')) & 0x8000 || (GetAsyncKeyState(static_cast<int>('W')) & 0x8000)) // 按 w 或 W 代表向上
		{
			if (hero_1->y > -19 && // 若未超出上边界
				(map_cell + (hero_1->x - 89) / 30 + ((hero_1->y + 19) / 30 - 1) * 15)->brick == 0 && // 且无砖块
				(map_cell + (hero_1->x - 89) / 30 + ((hero_1->y + 19) / 30 - 1) * 15)->brick_crack == 0 && // 且无可破坏砖块
				(map_cell + (hero_1->x - 89) / 30 + ((hero_1->y + 19) / 30 - 1) * 15)->if_bomb == false) // 且无炸弹
			{
				hero_1->move_direction = direction::up; // 运动方向向上
			}
			hero_1->stand_direction = direction::up; // 站立方向向上
		}
		if (GetAsyncKeyState(static_cast<int>('s')) & 0x8000 || GetAsyncKeyState(static_cast<int>('S')) & 0x8000) // 按 s 或 S 代表向下
		{
			if (hero_1->y < -19 + 12 * 30 && // 若未超出下边界
				(map_cell + (hero_1->x - 89) / 30 + ((hero_1->y + 19) / 30 + 1) * 15)->brick == 0 && // 且无砖块
				(map_cell + (hero_1->x - 89) / 30 + ((hero_1->y + 19) / 30 + 1) * 15)->brick_crack == 0 && // 且无可破坏砖块
				(map_cell + (hero_1->x - 89) / 30 + ((hero_1->y + 19) / 30 + 1) * 15)->if_bomb == false) // 且无炸弹
			{
					hero_1->move_direction = direction::down; // 运动方向向下
			}
			hero_1->stand_direction = direction::down; // 站立方向向下
		}
		if (GetAsyncKeyState(static_cast<int>('a')) & 0x8000 || GetAsyncKeyState(static_cast<int>('A')) & 0x8000) // 按 a 或 A 代表向左
		{
			if (hero_1->x > 89 && // 若未超出左边界
				(map_cell + (hero_1->x - 89) / 30 - 1 + (hero_1->y + 19) / 30 * 15)->brick == 0 && // 且无砖块
				(map_cell + (hero_1->x - 89) / 30 - 1 + (hero_1->y + 19) / 30 * 15)->brick_crack == 0 && // 且无可破坏砖块
				(map_cell + (hero_1->x - 89) / 30 - 1 + (hero_1->y + 19) / 30 * 15)->if_bomb == false) // 且无炸弹
			{
				hero_1->move_direction = direction::left; // 运动方向向左
			}
			hero_1->stand_direction = direction::left; // 站立方向向左
		}
		if (GetAsyncKeyState(static_cast<int>('d')) & 0x8000 || GetAsyncKeyState(static_cast<int>('D')) & 0x8000) // 按 d 或 D 代表向右
		{
			if (hero_1->x < 89 + 14 * 30 && // 若未超出右边界
				(map_cell + (hero_1->x - 89) / 30 + 1 + (hero_1->y + 19) / 30 * 15)->brick == 0 && // 且无砖块
				(map_cell + (hero_1->x - 89) / 30 + 1 + (hero_1->y + 19) / 30 * 15)->brick_crack == 0 && // 且无可破坏砖块
				(map_cell + (hero_1->x - 89) / 30 + 1 + (hero_1->y + 19) / 30 * 15)->if_bomb == false) // 且无炸弹
			{
				hero_1->move_direction = direction::right; // 运动方向向右
			}
			hero_1->stand_direction = direction::right; // 站立方向向右
		}
	}

	// 判断英雄 2 上一轮移动是否完成
	if (hero_2->death == false && hero_2->move_direction == direction::stand) // 若完成
	{
		if (GetAsyncKeyState(VK_UP) & 0x8000) // 按↑代表向上
		{
			if (hero_2->y > -19 && // 若未超出上边界
				(map_cell + (hero_2->x - 89) / 30 + ((hero_2->y + 19) / 30 - 1) * 15)->brick == 0 && // 且无砖块
				(map_cell + (hero_2->x - 89) / 30 + ((hero_2->y + 19) / 30 - 1) * 15)->brick_crack == 0 && // 且无可破坏砖块
				(map_cell + (hero_2->x - 89) / 30 + ((hero_2->y + 19) / 30 - 1) * 15)->if_bomb == false) // 且无炸弹
			{
				hero_2->move_direction = direction::up; // 运动方向向上
			}
			hero_2->stand_direction = direction::up; // 站立方向向上
		}
		if (GetAsyncKeyState(VK_DOWN) & 0x8000) // 按↓代表向下
		{
			if (hero_2->y < -19 + 12 * 30 && // 若未超出下边界
				(map_cell + (hero_2->x - 89) / 30 + ((hero_2->y + 19) / 30 + 1) * 15)->brick == 0 && // 且无砖块
				(map_cell + (hero_2->x - 89) / 30 + ((hero_2->y + 19) / 30 + 1) * 15)->brick_crack == 0 && // 且无可破坏砖块
				(map_cell + (hero_2->x - 89) / 30 + ((hero_2->y + 19) / 30 + 1) * 15)->if_bomb == false) // 且无炸弹
			{
				hero_2->move_direction = direction::down; // 运动方向向下
			}
			hero_2->stand_direction = direction::down; // 站立方向向下
		}
		if (GetAsyncKeyState(VK_LEFT) & 0x8000) // 按←代表向左
		{
			if (hero_2->x > 89 && // 若未超出左边界
				(map_cell + (hero_2->x - 89) / 30 - 1 + (hero_2->y + 19) / 30 * 15)->brick == 0 && // 且无砖块
				(map_cell + (hero_2->x - 89) / 30 - 1 + (hero_2->y + 19) / 30 * 15)->brick_crack == 0 && // 且无可破坏砖块
				(map_cell + (hero_2->x - 89) / 30 - 1 + (hero_2->y + 19) / 30 * 15)->if_bomb == false) // 且无炸弹
			{
				hero_2->move_direction = direction::left; // 运动方向向左
			}
			hero_2->stand_direction = direction::left; // 站立方向向左
		}
		if (GetAsyncKeyState(VK_RIGHT) & 0x8000) // 按→代表向右
		{
			if (hero_2->x < 89 + 14 * 30 && // 若未超出右边界
				(map_cell + (hero_2->x - 89) / 30 + 1 + (hero_2->y + 19) / 30 * 15)->brick == 0 && // 且无砖块
				(map_cell + (hero_2->x - 89) / 30 + 1 + (hero_2->y + 19) / 30 * 15)->brick_crack == 0 && // 且无可破坏砖块
				(map_cell + (hero_2->x - 89) / 30 + 1 + (hero_2->y + 19) / 30 * 15)->if_bomb == false) // 且无炸弹
			{
				hero_2->move_direction = direction::right; // 运动方向向右
			}
			hero_2->stand_direction = direction::right; // 站立方向向右
		}
	}
}

// 与用户输入无关的更新
void update_without_input()
{
	// 英雄死亡判断
	if ((map_cell + (hero_1->x - 89) / 30 + (hero_1->y + 19) / 30 * 15)->if_death == true) // 若英雄 1 碰到炸弹痕迹
	{
		hero_1->death = true; // 英雄 1 死亡
	}
	if ((map_cell + (hero_2->x - 89) / 30 + (hero_2->y + 19) / 30 * 15)->if_death == true) // 若英雄 2 碰到炸弹痕迹
	{
		hero_2->death = true; // 英雄 2 死亡
	}

	// 英雄 1 的道具得分
	if ((map_cell + (hero_1->x - 89) / 30 + (hero_1->y + 19) / 30 * 15)->tools > 0) // 若英雄 1 碰到道具
	{
		switch ((map_cell + (hero_1->x - 89) / 30 + (hero_1->y + 19) / 30 * 15)->tools)
		{
		case 1:
			hero_1->score += 4; // 30% 的概率得分加 4
			break;
		case 2:
			hero_1->score += 6; // 20% 的概率得分加 6
			break;
		case 3:
			hero_1->score += 10; // 10% 的概率得分加 10
			break;
		case 4:
			hero_1->score += 10; // 10% 的概率得分加 10
			break;
		case 5:
			hero_1->score += 15; // 5% 的概率得分加 15
			break;
		default:
			hero_1->score += 20; // 5% 的概率得分加 20
			break;
		}
		play_music_once(_T(R"(.\musics\tool.mp3)"), _T(R"(tool_hero_1)")); // 播放吃道具音乐
		(map_cell + (hero_1->x - 89) / 30 + (hero_1->y + 19) / 30 * 15)->tools = 0; // 让道具消失
	}
	// 英雄 2 的道具得分
	if ((map_cell + (hero_2->x - 89) / 30 + (hero_2->y + 19) / 30 * 15)->tools > 0) // 若英雄 2 碰到道具
	{
		switch ((map_cell + (hero_2->x - 89) / 30 + (hero_2->y + 19) / 30 * 15)->tools)
		{
		case 1:
			hero_2->score += 4; // 30% 的概率得分加 4
			break;
		case 2:
			hero_2->score += 6; // 20% 的概率得分加 6
			break;
		case 3:
			hero_2->score += 10; // 10% 的概率得分加 10
				break;
		case 4:
			hero_2->score += 10; // 10% 的概率得分加 10
				break;
		case 5:
			hero_2->score += 15; // 5% 的概率得分加 15
				break;
		default:
			hero_2->score += 20; // 5% 的概率得分加 20
			break;
		}
		play_music_once(_T(R"(.\musics\tool.mp3)"), _T(R"(tool_hero_2)")); // 播放吃道具音乐
		(map_cell + (hero_2->x - 89) / 30 + (hero_2->y + 19) / 30 * 15)->tools = 0; // 让道具消失
	}

	t_now = 120 - (time(nullptr) - t_start); // 计算倒计时。倒计时时间 = 倒计时总秒数 - 游戏显示主界面后经过的时间

	if (t_now <= 0) // 倒计时倒数为 0
	{
		mciSendString(_T("close background_music"), nullptr, 0, nullptr); // 关闭背景音乐
		play_music_once(_T(R"(.\musics\Bombit_-_level_complete.mp3)"), _T("complete")); // 播放胜利音乐
		draw_png(180, 130, img_time_end); // 绘制“时间到”
		FlushBatchDraw(); // 开始绘制
		Sleep(5000);  // 暂停 5 秒
		// 判断英雄 1 和英雄 2 的得分高低
		if (hero_1->score > hero_2->score) // 若英雄 1 得分高
		{
			game_end = 1; // 英雄 1 胜利
		}
		else if (hero_1->score < hero_2->score) // 若英雄 2 得分高
		{
			game_end = 2; // 英雄 2 胜利
		}
		else // 若得分相等
		{
			game_end = 3; // 平局
		}
	}
	
	if (brick_crack_create_num <= 0) // 若砖块总数为 0
	{
		mciSendString(_T("close background_music"), nullptr, 0, nullptr); // 关闭背景音乐
		play_music_once(_T(R"(.\musics\Bombit_-_level_complete.mp3)"), _T("complete")); // 播放胜利音乐
		draw_png(200, 160, img_game_end); // 绘制“游戏结束”
		FlushBatchDraw(); // 开始绘制
		Sleep(5000);  // 暂停 5 秒
		// 判断英雄 1 和英雄 2 的得分高低
		if (hero_1->score > hero_2->score) // 若英雄 1 得分高
		{
			game_end = 1; // 英雄 1 胜利
		}
		else if (hero_1->score < hero_2->score) // 若英雄 2 得分高
		{
			game_end = 2; // 英雄 2 胜利
		}
		else // 若得分相等
		{
			game_end = 3; // 平局
		}
	}

	if (hero_1->death == true && hero_2->death == true && all_death == false) // 若英雄 1 和英雄 2 同时死亡
	{
		all_death = true; // 英雄全部死亡标志位记为真
	}
	
	if (all_death == true && hero_1->hero_death / 4 - img_hero_death_num >= img_hero_death_smoke_num + 40 && hero_2->hero_death / 4 - img_hero_death_num >= img_hero_death_smoke_num + 40) // 若全部放完死亡动画
	{
		mciSendString(_T("close background_music"), nullptr, 0, nullptr); // 关闭背景音乐
		play_music_once(_T(R"(.\musics\Bombit_-_mission_failed.mp3)"), _T("failed")); // 播放失败音乐
		draw_png(200, 160, img_game_end); // 绘制“游戏结束”
		FlushBatchDraw(); // 开始绘制
		Sleep(6000);  // 暂停 6 秒
		game_end = 3; // 平局
	}
	else if (all_death == false)
	{
		if (hero_1->hero_death / 4 - img_hero_death_num >= img_hero_death_smoke_num + 40) // 若英雄 1 死亡且放完死亡动画
		{
			mciSendString(_T("close background_music"), nullptr, 0, nullptr); // 关闭背景音乐
			play_music_once(_T(R"(.\musics\Bombit_-_level_complete.mp3)"), _T("complete")); // 播放胜利音乐
			draw_png(200, 160, img_game_end); // 绘制“游戏结束”
			FlushBatchDraw(); // 开始绘制
			Sleep(5000);  // 暂停 5 秒
			game_end = 2; // 英雄 2 胜利
		}
		else if (hero_2->hero_death / 4 - img_hero_death_num >= img_hero_death_smoke_num + 40) // 若英雄 2 死亡且放完死亡动画
		{
			mciSendString(_T("close background_music"), nullptr, 0, nullptr); // 关闭背景音乐
			play_music_once(_T(R"(.\musics\Bombit_-_level_complete.mp3)"), _T("complete")); // 播放胜利音乐
			draw_png(200, 160, img_game_end); // 绘制“游戏结束”
			FlushBatchDraw(); // 开始绘制
			Sleep(5000);  // 暂停 5 秒
			game_end = 1; // 英雄 1 胜利
		}
	}
}

// 游戏结束
void game_over()
{
	RemoveFontResource(LR"(.\font\font.ttf)"); // 移除游戏字体
	EndBatchDraw(); // 结束结束批量绘制，并执行未完成的绘制任务
	closegraph(); // 关闭绘图窗口
}

